
import GridSystem from "@/GridSystem";
import { ClassName, CtrlType, AreaSelectMode, Events, SelectMode } from "../../Constants";
import { Utils } from "../../utils";
import Feature from "../Feature";
import Group from "./Group";

// 鼠标选取某个范围选中N个元素
class SelectArea extends Group {

    static instance: SelectArea | null = null;
    // 静态方法，用于获取单例实例  
    static getInstance(bool = false) {
        if (!SelectArea.instance) {
            SelectArea.instance = new SelectArea();
        }
        if (bool) SelectArea.instance.initEventListener();
        Feature.Gls.addFeature(SelectArea.instance);
        return SelectArea.instance;
    }

    selectMode: SelectMode = SelectMode.ONE_P;  // 是否框中一个点就判定为选中，还是全部点进入才判定选中
    drawMode: AreaSelectMode = AreaSelectMode.RECT;  // 绘制模式,多边形或者矩形

    constructor(fn = () => { }) {
        if (SelectArea.instance) {
            throw new Error("Error: Instantiation failed: Use SelectArea.getInstance() instead of new.");
        }
        super();
        this.callback = fn;
        this.className = ClassName.SELECTAREA;
        this.cbTransformChild = true;
        this.isDelWithChild = false;
        this.cbResize = true;
        this.zIndex = Infinity;  // 不要选中内部的元素
        this.fillStyle = 'rgba(152, 185, 246, .3)';
        this.hoverStyle = 'rgba(152, 185, 246, .5)';
        this.focusStyle = 'rgba(152, 185, 246, .7)';
        this.ctrlTypes = [CtrlType.SIZE_CTRL, CtrlType.ANGLE_CTRL, CtrlType.WIDTH_CTRL, CtrlType.HEIGHT_CTRL];
        this.initEventListener();
        SelectArea.instance = this;
    }

    initEventListener() {
        Feature.Gls.cbOperable = false;
        if (GridSystem.isMobile) {
            document.addEventListener(Events.TOUCHSTART, this.setPointArr);
        } else {
            document.addEventListener(Events.MOUSE_DOWN, this.setPointArr);
        }
    }

    setPointArr = (e: any) => {
        let startP = Feature.Gls.getRelativePos(Utils.getMousePos(Feature.Gls.domElement, e));
        this.pointArr[0] = startP;
        const mousemove = (ev: any) => {
            switch (this.drawMode) {
                case AreaSelectMode.RECT: {
                    let endP = Feature.Gls.getRelativePos(Utils.getMousePos(Feature.Gls.domElement, ev));
                    this.pointArr[1] = {
                        x: endP.x,
                        y: startP.y
                    }
                    this.pointArr[2] = {
                        x: endP.x,
                        y: endP.y
                    }
                    this.pointArr[3] = {
                        x: startP.x,
                        y: endP.y
                    }
                }
                    break;
                case AreaSelectMode.IRREGULAR: {
                    let moveP = Feature.Gls.getRelativePos(Utils.getMousePos(Feature.Gls.domElement, ev));
                    this.addPoint(moveP);
                }
                    break;
                default:
                    break;
            }
        }
        const mouseup = () => {
            Feature.Gls.cbOperable = true;
            let featuresIn = this.getSelectFeature();
            featuresIn.forEach(fi => this.addMember(fi))
            this.resize(true)
            Feature.Gls.enableBbox(this)
            document.removeEventListener(Events.MOUSE_DOWN, this.setPointArr)
            document.removeEventListener(Events.MOUSE_MOVE, mousemove)
            document.removeEventListener(Events.MOUSE_UP, mouseup)
            document.removeEventListener(Events.TOUCHSTART, this.setPointArr)
            document.removeEventListener(Events.TOUCHMOVE, mousemove)
            document.removeEventListener(Events.TOUCHEND, mouseup)
            this.dispatch(new CustomEvent(Events.SELECTED, { detail: '' }))   // 不要此事件,性能消耗比较大,凑合用画布的DRAW
        }
        if (GridSystem.isMobile) {
            document.addEventListener(Events.TOUCHMOVE, mousemove, { passive: false })
            document.addEventListener(Events.TOUCHEND, mouseup)
        } else {
            document.addEventListener(Events.MOUSE_MOVE, mousemove)
            document.addEventListener(Events.MOUSE_UP, mouseup)
        }
    }

    getSelectFeature() {
        let features = Feature.Gls.features.filter(f => Utils.isBasicFeature(f));  
        // let features = Feature.Gls.features.filter(f => Utils.isBasicFeature(f) && !f.parent && !f.group);   // !f.parent && !f.group 如果他有父元素会跟随父元素缩放,所以可以排除
        let featureIn = features.filter(f => {
            if (!f.cbSelect) return
            let pointArr = f.pointArr;
            if (this.selectMode === SelectMode.ALL_P) {
                return pointArr.every(p => {
                    return Utils.isPntInPolygon(p, this.pointArr);
                });
            }
            if (this.selectMode === SelectMode.ONE_P) {
                return pointArr.some(p => {
                    return Utils.isPntInPolygon(p, this.pointArr);
                });
            }
            return []
        })
        console.log(featureIn, "selectArea选中的元素");
        return featureIn
    }

    override destroy() {
        document.removeEventListener(Events.TOUCHSTART, this.setPointArr);
        document.removeEventListener(Events.MOUSE_DOWN, this.setPointArr);
        super.destroy();
    }
}

export default SelectArea;